﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Sgr;
using Sgr.BackGroundTasks;
using Sgr.EntityFrameworkCore;
using Sgr.EventBus;
using Sgr.EventBus.RelayBoxs;
using Sgr.EventBus.RelayBoxs.BackGroundTasks;
using Sgr.EventBus.RelayBoxs.Domain;
using Sgr.EventBus.RelayBoxs.Infrastructure;
using Sgr.EventBus.RelayBoxs.Infrastructure.Repositories;
using Sgr.EventBus.RelayBoxs.Services;
using Sgr.Generator.Segment;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class ServiceCollectionExtensions
    {
        public const string OutboxMessageProcessorBackGroundTaskId = "OutboxMessageProcessorBackGroundTask";

        public static IServiceCollection UseEventBusRelayBoxs<TContext>(this IServiceCollection services, IConfiguration configuration) where TContext : UnitOfWorkDbContext
        {
            services.TryAddEnumerable(ServiceDescriptor.Singleton<IEntityFrameworkTypeProvider, OutboxMessageEntityFrameworkTypeProvider>());
            services.TryAddEnumerable(ServiceDescriptor.Singleton<ISegmentProvider, OutboxMessageProvider>());

            if (services.Any(f => f.ServiceType == typeof(IEventBus)))
                services.Replace(ServiceDescriptor.Scoped<IEventBus, OutboxEventBus>());
            else
                services.TryAddScoped<IEventBus, OutboxEventBus>();

            if (services.Any(f => f.ServiceType == typeof(IOutboxMessageRepository)))
                services.Replace(ServiceDescriptor.Scoped<IOutboxMessageRepository, OutboxMessageRepository<TContext>>());
            else
                services.TryAddScoped<IOutboxMessageRepository, OutboxMessageRepository<TContext>>();

            // 配置后台任务
            services.AddOptions<RelayBoxOptions>()
                .BindConfiguration("Sgr:RelayBoxs");

            services.AddBackGroundTask<OutboxMessageProcessorBackGroundTask>();

            string cron = configuration.GetValue<string>("Sgr:BackGroundTasks:Cron:OutboxMessageProcessorBackGroundTask") ?? "0/5 * * * * ?"; // 每五秒执行一次
            services.Configure<BackGroundTaskOptions>(opts =>
            {
                opts.RegistRecurringTask<OutboxMessageProcessorBackGroundTask>(
                   OutboxMessageProcessorBackGroundTaskId,
                    "处理执行事件的周期性任务",
                    cron
                );
            });

            // 清理资源
            services.TryAddEnumerable(ServiceDescriptor.Scoped<ICleanupHandle, OutboxMessageCleanupHandle>());

            return services;
        }
    }
}